/* This file was created by Carbide.j */

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.rms.RecordStoreException;

public class ClickSMS extends MIDlet implements CommandListener {
	private ApplicationSettingForm mySettingsForm;
	private ApplicationSettings myStore;
	private AboutForm myAboutForm;
	private Form myForm;
	private TextField myToField;
	private TextField myMessageField;
	private StringItem myLastMsgIdField;
	private Command backCommand = new Command("Back", Command.BACK, 1);
	private Command sendMsgCommand = new Command("Send Message", Command.SCREEN, 1);
	private Command clearMsgCommand = new Command("Clear Message", Command.SCREEN, 1);
	private Command exitCommand = new Command("Exit", Command.EXIT, 1);
	private Command aboutCommand = new Command("About", Command.SCREEN, 1);
	private Command settingsCommand = new Command("Settings", Command.SCREEN, 1);
	private Command balanceCommand = new Command("Account Balance",	Command.SCREEN, 1);
	private Command coverageCommand = new Command("Coverage Query",	Command.SCREEN, 1);
	private Command msgStatusCommand = new Command("Last Message Status", Command.SCREEN, 1);
	private String myLastMessageId;

	// Alert to be displayed if error occurs.
	private Alert alert;

	public ClickSMS() {
		mySettingsForm = new ApplicationSettingForm();
		myAboutForm = new AboutForm();
		myAboutForm.addCommand(backCommand);
		myForm = new Form("ClickSMS");
		myToField = new TextField("To:", "", 12, TextField.PHONENUMBER);
		myMessageField = new TextField("Enter message:", "", 160, TextField.PLAIN);
		myLastMsgIdField = new StringItem("Last message ID:", "(no message sent)");
		myForm.append(myToField);
		myForm.append(myMessageField);
		myForm.append(myLastMsgIdField);
		myForm.addCommand(sendMsgCommand);
		myForm.addCommand(clearMsgCommand);
		myForm.addCommand(balanceCommand);
		myForm.addCommand(coverageCommand);
		myForm.addCommand(msgStatusCommand);
		myForm.addCommand(settingsCommand);
		myForm.addCommand(aboutCommand);
		myForm.addCommand(exitCommand);
		mySettingsForm.setCommandListener(this);
		myForm.setCommandListener(this);
		myAboutForm.setCommandListener(this);
	}

	public void startApp() {
		Display.getDisplay(this).setCurrent(myForm);
	}

	public void pauseApp() {
	}

	public void destroyApp(boolean a) throws MIDletStateChangeException {
		if (myStore != null) {
			myStore.destroy();
		}
	}

	public void commandAction(Command c, Displayable d) {
		if (c == exitCommand) {
			notifyDestroyed();
		}		
		if (c == backCommand) {
			Display.getDisplay(this).setCurrent(myForm);
		}
		if (c == sendMsgCommand) {
			sendMessage();
		}
		if (c== clearMsgCommand) {
			myMessageField.setString(null);
		}
		if (c == aboutCommand) {
			Display.getDisplay(this).setCurrent(myAboutForm);
		}
		if (c == balanceCommand) {
			getBalance();
		}
		if (c == coverageCommand) {
			coverageQuery();
		}
		if (c == msgStatusCommand) {
			queryMessage();
		}
		if (c == settingsCommand) {
			try {
				ApplicationSettings settings = getSettings();
				mySettingsForm.setFields(settings.getFrom(), settings
						.getApiID(), settings.getUsername(), settings
						.getPassword());
				Display.getDisplay(this).setCurrent(mySettingsForm);
			} catch (RecordStoreException e) {
				showAlert("Settings Error", "Could not retrieve settings: "
						+ e.getMessage(), mySettingsForm);
			}
		}
		if (c == mySettingsForm.getSaveCommand()) {
			try {
				ApplicationSettings settings = getSettings();
				settings.updateSettings(mySettingsForm.getFrom(),
						mySettingsForm.getAPIId(),
						mySettingsForm.getUsername(), mySettingsForm
								.getPassword());
				Display.getDisplay(this).setCurrent(myForm);
			} catch (RecordStoreException e) {
				showAlert("Settings Error", "Could not retrieve settings: "
						+ e.getMessage(), myForm);
			}
		}
		if (c == mySettingsForm.getBackCommand()) {
			Display.getDisplay(this).setCurrent(myForm);
		}
	}

	private synchronized ApplicationSettings getSettings()
			throws RecordStoreException {
		if (myStore == null) {
			myStore = new ApplicationSettings();
		}
		return myStore;
	}

	/**
	 * Shows alert with specified title and text. If next displayable is not
	 * specified then application will be closed after alert closing.
	 * 
	 * @param title
	 *            - Title of alert.
	 * @param message
	 *            - text of alert.
	 * @param nextDisp
	 *            - next displayable. Can be null.
	 */
	private void showAlert(String title, String message, Displayable nextDisp) {
		alert = new Alert(title);
		alert.setString(message);
		alert.setTimeout(Alert.FOREVER);
		Display display = Display.getDisplay(this);
		if (nextDisp != null) {
			display.setCurrent(alert, nextDisp);
		} else {
			display.setCurrent(alert);
			alert.setCommandListener(this);
		}
	}

	void getBalance() {
		try {
			ApplicationSettings settings = getSettings();
			StringBuffer  url = new StringBuffer("https://api.clickatell.com/http/getbalance?");
			url.append("api_id=" + settings.getApiID());
			url.append("&user="	+ URLEncoder.encode(settings.getUsername()));
			url.append("&password="	+ URLEncoder.encode(settings.getPassword()));
			PostingThread thread = new PostingThread(this, url.toString(), false);
			thread.start();
			showAlert("Please wait", "Retrieving account balance ...", myForm);
		} catch (Exception e) {
			showAlert("Error", e.getMessage(), myForm);
		}

	}

	void coverageQuery() {
		try {
			ApplicationSettings settings = getSettings();
			String to = stripPlus(myToField.getString());
			if (to.length() > 1) {
				StringBuffer  url = new StringBuffer("https://api.clickatell.com/utils/routeCoverage.php?");
				url.append("api_id=" + settings.getApiID());
				url.append("&user=" + URLEncoder.encode(settings.getUsername()));
				url.append("&password="	+ URLEncoder.encode(settings.getPassword()));
				url.append("&msisdn=" + to);
				PostingThread thread = new PostingThread(this, url.toString(), false);
				thread.start();
				showAlert("Please wait", "Checking coverage of number " + to
						+ " ...", myForm);
			} else {
				showAlert("Warning",
						"Enter a number to check in the To: field!", myForm);
			}
		} catch (Exception e) {
			showAlert("Error", e.getMessage(), myForm);
		}

	}

	void queryMessage() {
		try {
			ApplicationSettings settings = getSettings();
			if (myLastMessageId != null) {
				StringBuffer  url = new StringBuffer("https://api.clickatell.com/http/querymsg?");
				url.append("api_id=" + settings.getApiID());
				url.append("&user="	+ URLEncoder.encode(settings.getUsername()));
				url.append("&password="	+ URLEncoder.encode(settings.getPassword()));
				url.append("&apimsgid=" + myLastMessageId);
				PostingThread thread = new PostingThread(this, url.toString(), false);
				thread.start();
				showAlert("Please wait", "Checking status of message "
						+ myLastMessageId + " ...", myForm);
			} else {
				showAlert("Warning",
						"No status info for the last message sent!", myForm);
			}
		} catch (Exception e) {
			showAlert("Error", e.getMessage(), myForm);
		}

	}

	void sendMessage() {
		try {
			ApplicationSettings settings = getSettings();
			String from = stripPlus(settings.getFrom());
			String to = stripPlus(myToField.getString());
			String msg = myMessageField.getString();
			StringBuffer  url = new StringBuffer("https://api.clickatell.com/http/sendmsg?");
			url.append("api_id=" + settings.getApiID());
			url.append("&user="	+ URLEncoder.encode(settings.getUsername()));
			url.append("&password="	+ URLEncoder.encode(settings.getPassword()));
			if (from != null) {
				url.append("&from=" + from);
			}
			url.append("&to=" + to);
			url.append("&text=" + URLEncoder.encode(msg));
			PostingThread thread = new PostingThread(this, url.toString(), true);
			thread.start();
			showAlert("Please wait", "Sending message to " + to + " ...",
					myForm);
		} catch (Exception e) {
			showAlert("Error", e.getMessage(), myForm);
		}
	}

	private String stripPlus(String number) {
		String result = number;
		if (number.startsWith("+")) {
			result = number.substring(1);
		}
		return result;
	}

	public void notifyPostResult(String result, boolean isSms) {
		if (isSms) {
			if (result.startsWith("ID:")) {
				myLastMessageId = result.substring(4);
				myLastMsgIdField.setText(myLastMessageId);
			}
		}
		showAlert("Request Result", getStatus(result), myForm);
	}

	private String getStatus(String msg) {
		String status = null;
		try {
			final String field = "Status: ";
			int pos = msg.indexOf(field);
			if (pos > 0) {
				pos = pos + field.length();
				String codeStr = msg.substring(pos, pos + 3);
				int code = (Integer.valueOf(codeStr)).intValue();
				switch (code) {
				case 1:
					status = "Message unknown";
					break;
				case 2:
					status = "Message queued";
					break;
				case 3:
					status = "Delivered to gateway";
					break;
				case 4:
					status = "Received by recipient";
					break;
				case 5:
					status = "Error with message";
					break;
				case 6:
					status = "User cancelled message delivery";
					break;
				case 7:
					status = "Error delivering message";
					break;
				case 8:
					status = "OK";
					break;
				case 9:
					status = "Routing error";
					break;
				case 10:
					status = "Message expired";
					break;
				case 11:
					status = "Message queued for later delivery";
					break;
				case 12:
					status = "Out of credit";
					break;
				default:
					status = "Unknown status code returned!";
				}
			}
		} catch (Throwable e) {
			showAlert("Runtime error", e.getMessage(), myForm);
		}
		String result = msg;
		if (status != null) {
			result = msg + " (" + status + ")";
		}
		;
		return result;
	}
}
